package com.qf.recharge.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.qf.common.core.config.ThreadPoolConfig;
import com.qf.common.core.entity.Recharge;
import com.qf.common.core.exception.CustomerException;
import com.qf.common.core.utils.UserUtils;
import com.qf.common.pay.param.PayFinishParam;
import com.qf.common.redis.config.RedissonConfig;
import com.qf.common.redis.utils.RedisUtil;
import com.qf.common.rocket.utils.RocketMQUtils;
import com.qf.recharge.mapper.RechargeMapper;
import com.qf.recharge.param.RechargeParam;
import com.qf.recharge.service.RechargeService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBlockingQueue;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @author zdl
 * @date 2025/4/3
 */
@Service
@Slf4j
public class RechargeServiceImpl implements RechargeService {
    @Resource
    private RechargeMapper rechargeMapper;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private RocketMQUtils rocketMQUtils;

    @Resource
    private RedissonClient redissonClient;
    @Resource
    private ThreadPoolConfig threadPoolConfig;

    @Override
    public String addRecharge(RechargeParam rechargeParam) {
        if (!StringUtils.hasLength(rechargeParam.getToken())) {
            throw new CustomerException("3004", "请重新加载页面1");
        }
        Integer uid = UserUtils.getUser();
        String key = String.format("repeat:%s:%s", rechargeParam.getToken(), uid);
        if (!redisUtil.keyExist(key)) {
            throw new CustomerException("3004", "请重新加载页面2");
        }
        redisUtil.deleteObject(key);
//        String lua =
//                "if redis.call('EXISTS', KEYS[1]) == 1 then " +
//                        "redis.call('DEL', KEYS[1]) " +
//                        "return 1" +
//                        "end;"
//                        + "return 0";
//        ArrayList<String> keyList = new ArrayList<>();
//        keyList.add(key);
//        Long ret = (Long) redisUtil.executeLua(lua, keyList, new Object[]{});
//        if (ret.equals(0)) {
//            throw new CustomerException("3004", "请重新加载页面");
//        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        String randomStr = RandomUtil.randomNumbers(6);
        String orderNo = sdf.format(new Date()) + randomStr;
        // 向充值表中插入数据
        Recharge recharge = new Recharge();
        BeanUtils.copyProperties(rechargeParam, recharge);
        recharge.setUid(uid);
        recharge.setOrderNo(orderNo);
        rechargeMapper.insert(recharge);
        // 发送延迟消息
        // rocketMQUtils.sendDelayMsg("ORDER_TOPIC1",null,orderNo,30);

        // 获取redisson的阻塞队列，并将订单号放入队列，延迟30秒后消费
        RBlockingQueue<Object> queue = redissonClient.getBlockingQueue("orderQueue");
        RDelayedQueue<Object> delayedQueue = redissonClient.getDelayedQueue(queue);
        delayedQueue.offer(orderNo, 30, TimeUnit.SECONDS);
        return orderNo;
    }

    @Override
    public Recharge rechargeByOrderNo(String orderNo) {

        return rechargeMapper.selectOne(new LambdaQueryWrapper<Recharge>()
                .eq(Recharge::getOrderNo, orderNo));
    }

    @Override
    public void updateRecharge(PayFinishParam param) {
        Recharge recharge = rechargeMapper.selectOne(new LambdaQueryWrapper<Recharge>()
                .eq(Recharge::getOrderNo, param.getOrderNo()));
        // 只有待支付状态才可修改为支付完成状态
        if (recharge.getStatus().equals(1)) {
            // 比对金额，省略
            // 更新
            rechargeMapper.update(null, new LambdaUpdateWrapper<Recharge>()
                    .set(Recharge::getStatus, 2)
                    .set(Recharge::getPayTime, new Date())
                    .set(Recharge::getTradeNo, param.getTradeNo())
                    .eq(Recharge::getId, recharge.getId()));
        }
    }

    @Override
    public void closeOrder(String orderNo) {

        Recharge recharge = rechargeMapper.selectOne(new LambdaQueryWrapper<Recharge>()
                .eq(Recharge::getOrderNo, orderNo));
        // 只有待支付状态才可修改为支付完成状态
        if (recharge != null && recharge.getStatus().equals(1)) {
            // 关闭订单
            rechargeMapper.update(null, new LambdaUpdateWrapper<Recharge>()
                    .set(Recharge::getStatus, 4) // 关闭订单
                    .set(Recharge::getCloseTime, new Date())
                    .eq(Recharge::getId, recharge.getId()));
        }
    }

    /**
     * 启动一个线程监听订单队列，如果有订单超时未支付，则关闭订单
     */
    public void startCloseOrderThread() {
        new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()) {
                try {
                    // 阻塞获取订单号
                    String orderNo = (String) redissonClient.getBlockingQueue("orderQueue").take();
                    log.info("开始处理关单任务, orderNo: {}", orderNo);
                    this.closeOrder(orderNo);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    log.info("关单消费者线程被中断");
                    break;
                } catch (Exception e) {
                    log.error("处理关单任务异常", e);
                }
            }
        });
        log.info("订单关单消费者线程已启动");
    }
}
